﻿using System;
using System.Collections.Generic;
using System.Linq;
using Domain.Models;
using UI.Views;

namespace UI.Presenters
{
    public class RedactorPresenter
    {
        private readonly SubjectsHandler subjecthHandler;
        private readonly List<Subject> subjects;
        private readonly VariantsWorker variantsWorker;
        private readonly IRedactorView view;
        private bool doesAddQuestionButtonExist;


        public RedactorPresenter(IRedactorView redactorView)
        {
            view = redactorView;

            subjecthHandler = new SubjectsHandler(new BinarySaver<Subject>());
            subjects = subjecthHandler.LoadAllSubjects();
            foreach (Subject subject in subjects)
            {
                view.AddSubjectToComboBox(subject.Name);
            }

            variantsWorker = new VariantsWorker(new BinarySaver<Variant>());

            doesAddQuestionButtonExist = false;
        }

        private Subject GetCurrentSubject()
        {
            return GetSubjectByName(view.GetCurrentSubjectName());
        }

        public void DeleteQuestion(long questionToDeleteId)
        {
            int currentVariantIndex = view.GetCurrentVariantIndex();

            Question questionToDelete = GetCurrentSubject().GetVariants()[currentVariantIndex].Questions.Find(x => x.Id == questionToDeleteId);

            GetCurrentSubject().GetVariants()[currentVariantIndex].Questions.Remove(questionToDelete);

            view.Clear();
            FillViewWithQuestionsOfVariant(GetCurrentSubject().GetVariants()[currentVariantIndex]);
        }

        public void DeleteAnswer(long answerId)
        {
            Answer answerToDelete = GetAnswerById(answerId);

            int currentVariantIndex = view.GetCurrentVariantIndex();

            Question question = GetCurrentSubject().GetVariants()[currentVariantIndex].Questions.Find(x => x.Answers.Contains(answerToDelete));

            question.RemoveAnswer(answerToDelete);

            view.Clear();
            FillViewWithQuestionsOfVariant(GetCurrentSubject().GetVariants()[currentVariantIndex]);
        }

        private Answer GetAnswerById(long answerId)
        {
            int currentVariantIndex = view.GetCurrentVariantIndex();

            foreach (Question question in GetCurrentSubject().GetVariants()[currentVariantIndex].Questions)
            {
                Answer answerToDelete = question.Answers.SingleOrDefault(y => y.Id == answerId);
                if (answerToDelete != null)
                    return answerToDelete;
            }
            throw new ArgumentNullException();
        }

        public void AddAnswer(long questionId)
        {
            int currentVariantIndex = view.GetCurrentVariantIndex();
            Question question = GetCurrentSubject().GetVariants()[currentVariantIndex].Questions.Find(x => x.Id == questionId);
            question.AddAnswer("");

            view.Clear();
            FillViewWithQuestionsOfVariant(GetCurrentSubject().GetVariants()[currentVariantIndex]);
        }

        public void AddQuestion()
        {
            int currentVariantIndex = view.GetCurrentVariantIndex();
            GetCurrentSubject().GetVariants()[currentVariantIndex].Questions.Add(new Question(""));

            view.Clear();
            FillViewWithQuestionsOfVariant(GetCurrentSubject().GetVariants()[currentVariantIndex]);
        }

        public void EditQuestion(long questionId, string newQuestionText)
        {
            int currentVariantIndex = view.GetCurrentVariantIndex();
            GetCurrentSubject().GetVariants()[currentVariantIndex].Questions.Find(x => x.Id == questionId).Text = newQuestionText;
        }

        public void EditAnswer(long answerId, string newAnswerText)
        {
            int currentVariantIndex = view.GetCurrentVariantIndex();
            foreach (Question question in GetCurrentVariantQuestions())
            {
                Answer answerToEdit = question.Answers.FirstOrDefault(y => y.Id == answerId);
                if (answerToEdit != null)
                {
                    if (answerToEdit.Text == question.TrueAnswer)
                        question.SetTrueAnswer(newAnswerText);

                    answerToEdit.Text = newAnswerText;
                    view.RefreshComboBox(question.Id, question.Answers,
                                         question.Answers.FirstOrDefault(x => x.Text == question.TrueAnswer));
                }
            }
        }

        private List<Question> GetCurrentVariantQuestions()
        {
            var currentVariantIndex = view.GetCurrentVariantIndex();

            return GetCurrentSubject().GetVariants()[currentVariantIndex].Questions;
        }

        public bool IsEditingNumberCorrect(int currentVariant)
        {
            return currentVariant >= 0 && currentVariant < GetCurrentSubject().GetVariants().Count;
        }

        public void DeleteVariant()
        {
            int currentVariantIndex = view.GetCurrentVariantIndex();

            view.DeleteVariantFromCombobox(GetCurrentSubject().GetVariants()[currentVariantIndex].Number);

            variantsWorker.DeleteVariant(GetCurrentSubject().GetVariants()[currentVariantIndex]);

            GetCurrentSubject().GetVariants().Remove(GetCurrentSubject().GetVariants()[currentVariantIndex]);

            currentVariantIndex--;
            
            view.Clear();
            
            FillViewWithQuestionsOfVariant(GetCurrentSubject().GetVariants()[currentVariantIndex]);
        }

        public void ChangeTrueAnswer(long answerId)
        {
            int currentVariantIndex = view.GetCurrentVariantIndex();
            foreach (Question question in GetCurrentSubject().GetVariants()[currentVariantIndex].Questions)
            {
                Answer answer = question.Answers.FirstOrDefault(y => y.Id == answerId);
                if (answer != null)
                    question.SetTrueAnswer(answer.Text);
            }
        }

        public void CreateNewVariant(int newVariantNumber)
        {
            GetCurrentSubject().GetVariants().Add(new Variant(newVariantNumber));
            view.AddVariantToComboBox(newVariantNumber);

            view.Clear();

            var newVarianIndex = newVariantNumber - 1;

            FillViewWithQuestionsOfVariant(GetCurrentSubject().GetVariants()[newVarianIndex]);
        }

        public void CreateSubject(string newSubjectName)
        {
            subjects.Add(new Subject(newSubjectName));
            view.AddSubjectToComboBox(newSubjectName);

            view.Clear();
        }

        public void SaveVariant(int currentVariantNumber)
        {
            variantsWorker.SaveVariant(
                GetCurrentSubject().GetVariants()[GetVariantIndexFromNumber(currentVariantNumber)]);
        }

        public int GetVariantIndexFromNumber(int variantNumber)
        {
            return variantNumber - 1;
        }

        public void SaveSubject(string subjectName)
        {
            Subject subjectToSave = GetSubjectByName(subjectName);
            subjecthHandler.Save(subjectToSave);
        }

        private Subject GetSubjectByName(string subjectName)
        {
            var subjectId = (int) subjecthHandler.GetSubjectIdByName(subjectName, subjects);
            return subjects.Find(x => x.Id == subjectId);
        }

        

        public void LoadVariant(int variantNumber)
        {
            AddAddQuestionButtonIfNotExistYet();

            string currentSubjectName = view.GetCurrentSubjectName();

            Subject currentSubject = GetSubjectByName(currentSubjectName);

            view.Clear();

            FillViewWithQuestionsOfVariant(currentSubject.GetVariants()[variantNumber]);
        }

        public void LoadSubject(string subjectName)
        {
            view.Clear();

            FillViewWithVariantsOfSubject(GetSubjectByName(subjectName));
        }

        private void AddAddQuestionButtonIfNotExistYet()
        {
            if (doesAddQuestionButtonExist == false)
            {
                view.AddAddQuestionButton();
                doesAddQuestionButtonExist = true;
            }
        }

        private void FillViewWithVariantsOfSubject(Subject subject)
        {
            foreach (Variant variant in subject.GetVariants())
            {
                view.AddVariantToComboBox(variant.Number);
            }
        }

        private void FillViewWithQuestionsOfVariant(Variant variant)
        {
            foreach (Question question in variant.Questions)
                view.AddQuestion(question.Text, question.Id, question.Answers,
                                 question.Answers.FirstOrDefault(x => x.Text == question.TrueAnswer));
        }

        public void DeleteSubject(string subjectName)
        {
            var subjectToDelete = subjecthHandler.GetSubjectByName(subjectName, subjects);

            subjecthHandler.DeleteSubject(subjectToDelete);

            subjects.Remove(subjectToDelete);

            view.Clear();
        }
    }
}